package com.simpou.commons.utils.functional;

import com.simpou.commons.utils.behavior.Condition;
import com.simpou.commons.utils.lang.Conditionals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Operações úteis em iterações e loops.
 *
 * @author Jonas Pereira
 * @since 2013-06-19
 * @version 2013-07-01
 */
public class Iterations {

    public static <T> void execute(Iterable<T> iterable, VoidAction<T> action, Condition<T> stopCondition) {
        _execute(iterable, action, stopCondition);
    }
    
    public static <T> void execute(Iterable<T> iterable, VoidAction<T> action) {
        execute(iterable, action, null);
    }
    
    public static <T, E> List<E> execute(Iterable<T> iterable, Action<T, E> action, Condition<T> stopCondition) {
        return _execute(iterable, action, stopCondition);
    }
    
    public static <T, E> List<E> execute(Iterable<T> iterable, Action<T, E> action) {
        return execute(iterable, action, null);
    }

    private static <T, E> List<E> _execute(Iterable<T> iterable, Action<T, E> action, Condition<T> stopCondition) {
        final List<E> results = new ArrayList<E>();
        for (T item : iterable) {
            if(stopCondition!=null && Conditionals.check(item, stopCondition)){
                break;
            }
            try {
                final E result = action.execute(item);
                if (result != null) {
                    results.add(result);
                }
            } catch (Exception ex) {
                action.doOnError(item, ex);
            }
        }
        return results;
    }


    public static <T> List<T> filter(Iterable<T> values, Condition<T> includeCondition) {
        List<T> list = new ArrayList<T>();
        for(T t : values){
            if(includeCondition.check(t)){
                list.add(t);
            }
        }
        return list;
    }
}
